// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// T [author] rhyme_lph
// e [email]  rhymelph@gmail.com
// L [github] https://github.com/rhymelph

import 'dart:async';

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/entities/account_dashboard_entity.dart';
import 'package:finance_app/src/entities/account_entity.dart';
import 'package:finance_app/src/entities/payment_entity.dart';
import 'package:finance_app/src/http_service/http_account_service.dart';
import 'package:finance_app/src/http_service/http_dashboard_service.dart';
import 'package:finance_app/src/http_service/http_payment_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/mixin/format_group_map_mixin.dart';
import 'package:finance_app/src/mixin/time_sort_mixin.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/widgets/bottom_sheet/accounts_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/dashboard_add_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/got_it_tip_bottom_sheet.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

class CashAndBankProvider extends BaseProvider<List<AccountEntity>>
    with
        TimeSortMixin,
        FormatGroupMapLocalMixin<PaymentEntity>,
        CheckPlanMixin {
  AccountEntity currentAccount;

  List<String> menuList = ['Edit', 'Delete'];

  AccountDashboardEntity accountDashboard;

  List<PaymentEntity> paymentList;

  RefreshController refreshController = RefreshController();

  bool buttonBarIsUp = true;
  ScrollController controller = ScrollController();

  void handleScrollUpdate(ScrollController controller) {
    if (controller.position.userScrollDirection == ScrollDirection.reverse &&
        buttonBarIsUp == true) {
      //向下滑动
      buttonBarIsUp = false;
      update();
    }
    if (controller.position.userScrollDirection == ScrollDirection.forward &&
        buttonBarIsUp == false) {
      buttonBarIsUp = true;
      update();
    }
  }

  @override
  Future get dataFuture => HttpAccountService.accountList();

  @override
  void initState() {
    super.initState();
    _loadAccountDashboard();
    _loadTransactionData();
    controller.addListener(() {
      handleScrollUpdate(controller);
    });
  }

  void onRefreshData() async {
    await _loadAccountDashboard();
    await _loadTransactionData();
    refreshController.refreshCompleted();
  }

  // 更改账号
  void onChangeAccount() {
    if (data == null) return;
    obtainContext?.call((context) async {
      final result = await showAccountsBottomSheet(
        context,
        onChangeAccount: (AccountEntity account) {
          if (account == null) {
            Navigator.of(context).pop(1);
          } else {
            Navigator.of(context).pop(account);
          }
        },
        onCreateAccount: onNavAddBank,
        accounts: List.of(data),
        // .where((element) => element.accountNumber != null)
        // .toList(),
        accountId: currentAccount?.id,
      );
      onChangeAccountJust(result);
    });
  }

  void onChangeAccountJust(dynamic result) {
    if (result != null) {
      if (result == 1) {
        currentAccount = null;
      } else {
        currentAccount = result;
      }
      update();
      onRequestRefresh();
    }
  }

  String getAccountName() {
    if (currentAccount?.bankName == null) {
      return S.current.all_accounts;
    } else {
      return '${currentAccount.bankName} ${currentAccount?.accountNumber ?? ''}';
    }
  }

  void onNavBankDetail(AccountEntity value) {
    onChangeAccountJust(value);
  }

  void onNavAddBank() async {
    if (isPlanExpired()) return;
    final result =
        await Routes.navigateTo(RouterGenProviders.addBankAccountPage);
    if (result != null && result is AccountEntity) {
      data.add(result);
      update();
    }
  }

  @override
  Future<void> onRefresh() async {
    await loadAccount();
    await _loadAccountDashboard();
    _loadTransactionData();
  }

  @override
  void unFocus() {}

  void onNavViewAll() async {
    await Routes.navigateTo(RouterGenProviders.allPaymentPage, params: {
      'accountId': currentAccount?.id,
      'accountName': currentAccount == null
          ? null
          : '${currentAccount?.bankName} ${currentAccount?.accountNumber ?? ''}',
    });
    _loadTransactionData();
  }

  void onNavPayment(PaymentEntity e) async {
    var result;
    if (e.type == 'transfer') {
      result = await Routes.navigateTo(
          RouterGenProviders.newAccountTransferPage,
          params: {
            'data': e,
            'isSelectMode': true,
          });
    } else if (e.flowType == 'out') {
      result = await Routes.navigateTo(RouterGenProviders.newCashOutPage,
          params: {'paymentData': e, 'isSelectMode': true});
    } else if (e.flowType == 'in') {
      result = await Routes.navigateTo(RouterGenProviders.newCashInPage,
          params: {'paymentData': e, 'isSelectMode': true});
    }
    _loadAccountDashboard();
    if (result != null && result is Map && result['delete'] == true) {
      paymentList.remove(e);
      contactToMap(paymentList);
      update();
      loadAccount();
    } else if (result != null && result is PaymentEntity) {
      e.fromJson(e.toJson());
      update();
      loadAccount();
    }
  }

  @override
  FutureOr<List<AccountEntity>> transformData(
      List<AccountEntity> d, bool isCache) {
    return super.transformData(d, isCache);
  }

  void onSelectMenu(String value) {
    switch (value) {
      case 'Edit':
        onEdit();
        break;
      case 'Delete':
        onDelete();
        break;
    }
  }

  void onDelete() {
    obtainContext?.call((context) async {
      bool isSuccess = await showDeleteAccountInfoBottomSheet(context);
      if (isSuccess) {
        isSuccess = false;
        await post(HttpAccountService.deleteAccount(currentAccount.id),
            autoHandler: AutoHandler.Toast,
            loadingTip: 'Loading....', onSuccess: (result) {
          isSuccess = true;
        });
        if (isSuccess) {
          data.remove(currentAccount);
          currentAccount = null;
          update();
          await showAccountDeleteSuccessBottomSheet(context);
          onRequestRefresh();
        }
      }
    });
  }

  void onEdit() async {
    currentAccount.hasUsed = paymentList.length > 0;
    final result = await Routes.navigateTo(
        RouterGenProviders.addBankAccountPage,
        params: {'data': currentAccount});
    if (result != null) {
      //更新已存在的数据
      data.remove(currentAccount);
      data.add(result);
      currentAccount = result;
      update();
    }
  }

  void onAdd() {
    if (isPlanExpired()) return;
    obtainContext?.call((context) async {
      await showDashboardAddBottomSheet(context,
          dashTypes: [DashBoardAddType.accountTransaction]);
      _loadAccountDashboard();
    });
  }

  // 加载看板数据
  Future<void> _loadAccountDashboard() async {
    await post(
        HttpDashboardService.dashboardAccount(
          accountId: currentAccount?.id,
          start_date: startTime,
          end_date: endTime,
        ),
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      accountDashboard = getEntityFromResult<AccountDashboardEntity>(result);
      update();
    });
  }

  Future<void> _loadTransactionData() async {
    await post(
        HttpPaymentService.paymentList(
            startDate: startTime,
            endDate: endTime,
            accountId: currentAccount?.id?.toString()),
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      paymentList = getEntityFromResult<List<PaymentEntity>>(result);
      if (paymentList.length > 0) {
        menuList = ['Edit'];
      } else {
        menuList = ['Edit', 'Delete'];
      }
      contactToMap(paymentList);
      update();
    });
  }

  void contactToMap(List<PaymentEntity> list) {
    groupMap.clear();
    sortGroupToMap(list,
        sort: (b, a) => sortIssuesAt(a, b, (t) => t.issuedAt, (t) => t.id),
        group: (a) => groupMonth(a, (t) => t.issuedAt));
  }

  Future<void> loadAccount() async {
    await post(dataFuture, onSuccess: (result) {
      data = transformData(
          getEntityFromResult<List<AccountEntity>>(result), false);
      if (currentAccount != null) {
        currentAccount = data.firstWhere(
            (element) => element.id == currentAccount.id,
            orElse: () => null);
      }
      update();
    });
  }
}
